/** 
    @file lua_scripted.hpp
    @brief Interface for lua-scripted objects
*/

#ifndef PM3_LUA_SCRIPTED_HPP
#define PM3_LUA_SCRIPTED_HPP

extern "C"{
    #include "lua.h"
    #include "lualib.h"
    #include "lauxlib.h"
}

#include "../logger.hpp"
#include "../util.hpp"

#include <OgreTimer.h>

namespace pm3 {
    namespace lua {
        /**
            @brief Lua command that reports something to the log
            @param[in] p_lua_state Pointer to the lua state
            @return Number of return values
            @note Should only be used by Lua
        */
        int log( lua_State *p_lua_state );
    }

    /**
        @class LUA_SCRIPTED
        @brief Abstract class for objects scripted with lua
    */
    class LUA_SCRIPTED {
    public:
            /**
                @brief Constructor
            */
            LUA_SCRIPTED();
            /**
                @brief Destructor
            */
            virtual ~LUA_SCRIPTED();

            /**
                @brief Loads a luascript
                @param[in] r_script Reference to the path of the script to be loaded
            */
            bool load( const std::string &r_script );

            /**
                @brief Unloads the luascript
            */
            virtual void unload() = 0;

            /**
                @brief Updates the scriptable object from the script
            */
            virtual void update();

            /**
                @brief Gets the active directory of the script
                @return The active directory
            */
            inline std::string get_directory() const {
                return pm3::util::extract_dir( m_script_path );
            }

            /**
                @brief Gets the script path
                @return Script path string
            */
            inline std::string get_script() const {
                return m_script_path;
            }

            /**
                @brief Parses the script and extracts callback contents
                @param[in] r_name Reference to the name of the callback
                @return Callback contents
            */
            std::string get_callback_contents( const std::string &r_name );

            /**
                @brief Does the script have any unsaved changes?
                @return True if it does, otherwise false
            */
            inline bool is_unsaved() const {
                return m_unsaved;
            }

    protected:
            /**
                @brief Binds C++ functions called by lua
            */
            virtual void bind() = 0;

            /**
                @brief Binds basic C++ functions called by lua
            */
            void bind_basic();

            //! Lua script path to be set after a successful loading
            std::string m_script_path;
            //! Lua state
            lua_State *m_lua_state;
            //! Timer for updating the scriptable object from the script
            Ogre::Timer m_timer;

            //! Does the script have any unsaved changes?
            bool m_unsaved;
    };

    //! Wrappers and globals for C++ functions exposed to lua
    namespace lua {}
}

#endif

